home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / MNetsrc.hqx / Mac TCP_IP Source v.33 / ax25.c < prev    next >
Text File  |  1989-04-06  |  11KB  |  404 lines

  1. /* Low level AX.25 frame processing - address header */
  2.  
  3. #include <stdio.h>
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "iface.h"
  7. #include "timer.h"
  8. #include "arp.h"
  9. #include "slip.h"
  10. #include "ax25.h"
  11. #include "lapb.h"
  12. #include <ctype.h>
  13. #ifdef MAC
  14. #include "unix.h"
  15. #include "heard.h"
  16. #endif
  17.  
  18. /* AX.25 broadcast address: "QST-0" in shifted ascii */
  19. struct ax25_addr ax25_bdcst = {
  20.     'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1,
  21.     ('0'<<1) | E,
  22. };
  23. char axbdcst[AXALEN];    /* Same thing, network format */
  24. struct ax25_addr mycall;
  25. int digipeat = 1;    /* Controls digipeating */
  26.  
  27. /* Send IP datagrams across an AX.25 link */
  28. int
  29. ax_send(bp,interface,gateway,precedence,delay,throughput,reliability)
  30. struct mbuf *bp;
  31. struct interface *interface;
  32. int32 gateway;
  33. char precedence;
  34. char delay;
  35. char throughput;
  36. char reliability;
  37. {
  38.     char *hw_addr,*res_arp();
  39.     struct ax25_cb *axp,*find_ax25(),*open_ax25();
  40.     struct ax25 addr;
  41.     struct ax25_addr destaddr;
  42.     struct mbuf *tbp;
  43.     extern int16 axwindow;
  44.     void ax_incom();
  45.     int16 size,bsize,seq;
  46.  
  47.     if((hw_addr = res_arp(interface,ARP_AX25,gateway,bp)) == NULLCHAR)
  48.         return 0;    /* Wait for address resolution */
  49.  
  50.     if(delay || (!reliability && (interface->flags == DATAGRAM_MODE))){
  51.         /* Use UI frame */
  52.         return (*interface->output)(interface,hw_addr,
  53.             interface->hwaddr,PID_FIRST|PID_LAST|PID_IP,bp);
  54.     }
  55.     /* Reliability is needed; use I-frames in AX.25 connection */
  56.     memcpy(destaddr.call,hw_addr,ALEN);
  57.     destaddr.ssid = hw_addr[ALEN];
  58.  
  59.     if((axp = find_ax25(&destaddr)) == NULLAX25 ||
  60.        (axp->state != CONNECTED && axp->state != RECOVERY)){
  61.         /* Open a new connection or reinitialize the old one */
  62.         atohax25(&addr,hw_addr,(struct ax25_addr *)interface->hwaddr);
  63.         axp = open_ax25(&addr,axwindow,ax_incom,NULLVFP,NULLVFP,interface,(char *)0);
  64.         if(axp == NULLAX25){
  65.             free_p(bp);
  66.             return -1;
  67.         }
  68.     }
  69.     /* If datagram is too big for one frame, send all but the last with
  70.      * the extension PID. Note: the copy to a new buf is necessary because
  71.      * AX.25 may continue retransmitting the frame after a local TCB has
  72.      * gone away, and using the buf directly would cause heap garbage to be
  73.      * transmitted. Besides, nobody would ever use AX.25 anywhere
  74.      * high performance is needed anyway...
  75.      */
  76.     bsize = len_mbuf(bp);
  77.     seq = 0;
  78.     while(bsize != 0){
  79.         size = min(bsize,axp->paclen);
  80.         /* Allocate buffer, allowing space for PID */
  81.         if((tbp = alloc_mbuf(size + 1)) == NULLBUF)
  82.             break;        /* out of memory! */
  83.         *tbp->data = PID_IP;
  84.         if(seq++ == 0)
  85.             *tbp->data |= PID_FIRST;     /* First in sequence */
  86.         if(size == bsize)
  87.             *tbp->data |= PID_LAST;        /* That's all of it */
  88.         /* else more to follow */
  89.  
  90.         tbp->cnt = 1;
  91.         tbp->cnt += pullup(&bp,tbp->data + 1,size);
  92.         send_ax25(axp,tbp);
  93.         bsize -= size;
  94.     }
  95.     free_p(bp);    /* Shouldn't be necessary */
  96.     return 0;
  97. }
  98. /* Add AX.25 link header and send packet.
  99.  * Note that the calling order here must match ec_output
  100.  * since ARP also uses it.
  101.  */
  102. int
  103. ax_output(interface,dest,source,pid,data)
  104. struct interface *interface;
  105. char *dest;        /* Destination AX.25 address (7 bytes, shifted) */
  106.             /* Also includes digipeater string */
  107. char *source;        /* Source AX.25 address (7 bytes, shifted) */
  108. char pid;        /* Protocol ID */
  109. struct mbuf *data;    /* Data field (follows PID) */
  110. {
  111.     struct mbuf *abp,*cbp,*htonax25();
  112.     struct ax25 addr;
  113.     
  114.     /* Allocate mbuf for control and PID fields, and fill in */
  115.     if((cbp = pushdown(data,2)) == NULLBUF){
  116.         free_p(data);
  117.         return -1;
  118.     }
  119.     cbp->data[0] = UI;
  120.     cbp->data[1] = pid;
  121.  
  122.     atohax25(&addr,dest,(struct ax25_addr *)source);
  123.     if((abp = htonax25(&addr,cbp)) == NULLBUF){
  124.         free_p(cbp);    /* Also frees data */
  125.         return -1;
  126.     }
  127.     /* This shouldn't be necessary because redirection has already been
  128.      * done at the IP router layer, but just to be safe...
  129.      */
  130.     if(interface->forw != NULLIF)
  131.         return (*interface->forw->raw)(interface->forw,abp);
  132.     else
  133.         return (*interface->raw)(interface,abp);
  134. }
  135. /* Process incoming AX.25 packets.
  136.  * After optional tracing, the address field is examined. If it is
  137.  * directed to us as a digipeater, repeat it.  If it is addressed to
  138.  * us or to QST-0, kick it upstairs depending on the protocol ID.
  139.  */
  140. int
  141. ax_recv(interface,bp)
  142. struct interface *interface;
  143. struct mbuf *bp;
  144. {
  145.     void arp_input();
  146.     int ip_route();
  147.     struct ax25_addr *ap;
  148.     struct mbuf *htonax25(),*hbp;
  149.     char multicast;
  150.     int nrnodes = 0;
  151.     char control;
  152.     struct ax25 hdr;
  153.     struct ax25_cb *axp,*find_ax25(),*cr_ax25();
  154.     struct ax25_addr ifcall;
  155.     extern struct ax25_addr nr_nodebc ;
  156. #ifdef MAC
  157.     struct heard_stuff *hp;
  158.     extern struct ax25_heard heard;
  159.     int16 type;
  160.     int16 prev, curr;
  161. #endif
  162.  
  163.     /* Use the address associated with this interface */
  164.     memcpy(ifcall.call,interface->hwaddr,ALEN);
  165.     ifcall.ssid = interface->hwaddr[ALEN];
  166.  
  167.     /* Pull header off packet and convert to host structure */
  168.     if(ntohax25(&hdr,&bp) < 0){
  169.         /* Something wrong with the header */
  170.         free_p(bp);
  171.         return;
  172.     }
  173. #ifdef MAC    
  174.     if (heard.enabled) {
  175.         /* scan heard list.  if not there, add it */
  176.         prev = -1;
  177.         curr = heard.first;
  178.         while (1) {
  179.             if (curr != -1) {
  180.                 hp = &heard.list[curr];
  181.                 if (addreq(&hp->info.source, &hdr.source)) {
  182.                     hp->htime = time(NULL);
  183.                     /* if not the first, make it so */
  184.                     if (prev != -1) {
  185.                         heard.list[prev].next = hp->next;
  186.                         hp->next = heard.first;
  187.                         heard.first = curr;
  188.                     }
  189.                     break;
  190.                 }
  191.             }
  192.  
  193.             /* if the last one, add another if room, or overwrite it */
  194.             if (curr == -1 || hp->next == -1) {
  195.                 /* not in heard list, add it.  if no room, bump oldest */
  196.                 if (heard.cnt < MAX_HEARD) {
  197.                     heard.list[heard.cnt].next = heard.first;
  198.                     heard.first = heard.cnt;
  199.                     hp = &heard.list[heard.cnt++];
  200.                 } else {
  201.                     heard.list[prev].next = -1;
  202.                     heard.list[curr].next = heard.first;
  203.                     heard.first = curr;
  204.                     hp = &heard.list[curr];
  205.                 }
  206.                 hp->flags = 0;
  207.                 memcpy(&hp->info, &hdr, sizeof(struct ax25));
  208.                 hp->htime = time(NULL);
  209.                 break;
  210.             }
  211.     
  212.             prev = curr;
  213.             curr = hp->next;
  214.         }
  215.         
  216.         /* figure out what the other station is running */
  217.         if (bp->cnt >= 2) {
  218.             type = ftype(*bp->data);
  219.             if(type == I || type == UI){    
  220.                 switch(*(bp->data + 1) & 0x3f){
  221.                 case PID_ARP:
  222.                     hp->flags |= HEARD_ARP;
  223.                     break;
  224.                 case PID_NETROM:
  225.                     hp->flags |= HEARD_NETROM;
  226.                     break;
  227.                 case PID_IP:
  228.                     hp->flags |= HEARD_IP;
  229.                     break;
  230.                 }
  231.             }
  232.         }
  233.     } else {
  234.         hp = NULL;
  235.     }
  236. #endif
  237.     /* Scan, looking for our call in the repeater fields, if any.
  238.      * Repeat appropriate packets.
  239.      */
  240.     for(ap = &hdr.digis[0]; ap < &hdr.digis[hdr.ndigis]; ap++){
  241.         if(ap->ssid & REPEATED)
  242.             continue;    /* Already repeated */
  243.         /* Check if packet is directed to us as a digipeater */
  244.         if(digipeat && addreq(ap,&ifcall)){
  245.             /* Yes, kick it back out */
  246.             ap->ssid |= REPEATED;
  247.             if((hbp = htonax25(&hdr,bp)) != NULLBUF){
  248.                 if(interface->forw != NULLIF)
  249.                     (*interface->forw->raw)(interface->forw,hbp);
  250.                 else
  251.                     (*interface->raw)(interface,hbp);
  252.                 bp = NULLBUF;
  253.             }
  254.         }
  255.         free_p(bp);    /* Dispose if not forwarded */
  256.         return;
  257.     }
  258.     /* Packet has passed all repeaters, now look at destination */
  259.     if(addreq(&hdr.dest,&ax25_bdcst)){
  260.         multicast = 1;    /* Broadcast packet */
  261.     } else if(addreq(&hdr.dest,&ifcall)){
  262.         multicast = 0;    /* Packet directed at us */
  263.     } else if(addreq(&hdr.dest,&nr_nodebc)){
  264.         nrnodes = 1 ;
  265.     } else {
  266.         /* Not for us */
  267.         free_p(bp);
  268.         return;
  269.     }
  270.     if(bp == NULLBUF){
  271.         /* Nothing left */
  272.         return;
  273.     }
  274.     /* Sneak a peek at the control field. This kludge is necessary because
  275.      * AX.25 lacks a proper protocol ID field between the address and LAPB
  276.      * sublayers; a control value of UI indicates that LAPB is to be
  277.      * bypassed.
  278.      */
  279.     control = *bp->data & ~PF;
  280.     if(uchar(control) == UI){
  281.         char pid;
  282.  
  283.         (void) pullchar(&bp);
  284.         if(pullup(&bp,&pid,1) != 1)
  285.             return;        /* No PID */
  286.         /* NET/ROM is very poorly layered. The meaning of the stuff
  287.          * following the PID of CF depends on what's in the AX.25 dest
  288.          * field.
  289.          */
  290.         if(nrnodes){
  291.             if(uchar(pid) == (PID_NETROM | PID_FIRST | PID_LAST))
  292.                 nr_nodercv(interface,&hdr.source,bp) ;
  293.             else     /* regular UI packets to "nodes" aren't for us */
  294.                 free_p(bp) ;
  295.             return ;
  296.         }
  297.         /* Handle packets. Multi-frame messages are not allowed */
  298.         switch(pid & (PID_FIRST | PID_LAST | PID_PID)){
  299.         case (PID_IP | PID_FIRST | PID_LAST):
  300.             ip_route(bp,multicast);
  301.             break;
  302.         case (PID_ARP | PID_FIRST | PID_LAST):
  303.             arp_input(interface,bp);
  304.             break;
  305.         default:
  306.             free_p(bp);
  307.             break;
  308.         }
  309.         return;
  310.     }
  311.     
  312.     /* Everything from here down is LAPB stuff, so drop anything
  313.      * not directed to us:
  314.      */
  315.  
  316.     if (multicast || nrnodes) {
  317.         free_p(bp) ;
  318.         return ;
  319.     }
  320.         
  321.     /* Find the source address in hash table */
  322.     if((axp = find_ax25(&hdr.source)) == NULLAX25){
  323.         /* Create a new ax25 entry for this guy,
  324.          * insert into hash table keyed on his address,
  325.          * and initialize table entries
  326.          */
  327.         if((axp = cr_ax25(&hdr.source)) == NULLAX25){
  328.             free_p(bp);
  329.             return;
  330.         }
  331.         axp->interface = interface;
  332.         /* Swap source and destination, reverse digi string */
  333.         ASSIGN(axp->addr.dest,hdr.source);
  334.         ASSIGN(axp->addr.source,hdr.dest);
  335.         if(hdr.ndigis > 0){
  336.             int i,j;
  337.  
  338.             /* Construct reverse digipeater path */
  339.             for(i=hdr.ndigis-1,j=0;i >= 0;i--,j++){
  340.                 ASSIGN(axp->addr.digis[j],hdr.digis[i]);
  341.                 axp->addr.digis[j].ssid &= ~(E|REPEATED);
  342.             }
  343.             /* Scale timers to account for extra delay */
  344.             axp->t1.start *= hdr.ndigis+1;
  345.             axp->t2.start *= hdr.ndigis+1;
  346.             axp->t3.start *= hdr.ndigis+1;
  347.         }
  348.         axp->addr.ndigis = hdr.ndigis;
  349.     }
  350.     if(hdr.cmdrsp == UNKNOWN)
  351.         axp->proto = V1;    /* Old protocol in use */
  352.     else
  353.         axp->proto = V2;
  354.  
  355.     lapb_input(axp,hdr.cmdrsp,bp);
  356. }
  357. /* Initialize AX.25 entry in arp device table */
  358. /* General purpose AX.25 frame output */
  359. int
  360. sendframe(axp,cmdrsp,ctl,data)
  361. struct ax25_cb *axp;
  362. char cmdrsp;
  363. char ctl;
  364. struct mbuf *data;
  365. {
  366.     struct mbuf *hbp,*cbp,*htonax25();
  367.     int i;
  368.  
  369.     if(axp == NULLAX25 || axp->interface == NULLIF)
  370.         return -1;
  371.  
  372.     /* Add control field */
  373.     if((cbp = pushdown(data,1)) == NULLBUF){
  374.         free_p(data);
  375.         return -1;
  376.     }
  377.     cbp->data[0] = ctl;
  378.  
  379.     axp->addr.cmdrsp = cmdrsp;
  380.     /* Create address header */
  381.     if((hbp = htonax25(&axp->addr,cbp)) == NULLBUF){
  382.         free_p(cbp);
  383.         return -1;
  384.     }
  385.     /* The packet is all ready, now send it */
  386.     if(axp->interface->forw != NULLIF)
  387.         i = (*axp->interface->forw->raw)(axp->interface->forw,hbp);
  388.     else
  389.         i = (*axp->interface->raw)(axp->interface,hbp);
  390.  
  391.     return i;
  392. }
  393. axarp()
  394. {
  395.     int psax25(),setpath();
  396.  
  397.     memcpy(axbdcst,ax25_bdcst.call,ALEN);
  398.     axbdcst[ALEN] = ax25_bdcst.ssid;
  399.  
  400.     arp_init(ARP_AX25,AXALEN,PID_FIRST|PID_LAST|PID_IP,
  401.      PID_FIRST|PID_LAST|PID_ARP,axbdcst,psax25,setpath);
  402. }
  403.  
  404.